home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / pcscheme / geneva / sources.exe / SOURCES / ASM / BIOSIO.ASM < prev    next >
Encoding:
Assembly Source File  |  1993-11-09  |  23.7 KB  |  651 lines

  1. ;* BIOSIO.ASM
  2. ;************************************************************************
  3. ;*                                    *
  4. ;*        PC Scheme/Geneva 4.00 Borland TASM code            *
  5. ;*                                    *
  6. ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT        *
  7. ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva    *
  8. ;*                                    *
  9. ;*----------------------------------------------------------------------*
  10. ;*                                    *
  11. ;*            Bios interface for I/O                *
  12. ;*                                    *
  13. ;*----------------------------------------------------------------------*
  14. ;*                                    *
  15. ;* Created by: John Jensen        Date: 1985            *
  16. ;* Revision history:                            *
  17. ;* - 18 Jun 92:    Renaissance (Borland Compilers, ...)            *
  18. ;*                                    *
  19. ;*                    ``In nomine omnipotentii dei''    *
  20. ;************************************************************************
  21. ;* This module contains some "C" procedures wich save more register than*
  22. ;* C conventions need. It shouldn't be considered as an heresy since    *
  23. ;* these procedures are fully conform to C rules; but it might        *
  24. ;* significantly decrease the size of the object code since these    *
  25. ;* procedures are called very often from assembly routines wich use    *
  26. ;* all CPU registers                            *
  27. ;************************************************************************
  28. IDEAL
  29. %PAGESIZE    60, 132
  30. MODEL    medium
  31. LOCALS    @@
  32.  
  33.     INCLUDE    "scheme.ash"
  34.  
  35. RFILE    EQU      03FH               ; read from a file
  36. WFILE    EQU      040H               ; write to a file
  37. MOVPTR    EQU      042H               ; move file pointer
  38.  
  39. CURSMASK EQU    01100000b        ; cursor status bits
  40. NOCURSOR EQU    00100000b         ; byte mask to disable cursor
  41.  
  42. DATASEG
  43.  
  44. curs_sav     DW    NOCURSOR*100h    ; For saving the cursor size when it's
  45. mouse_use    DW    0        ; are we using the mouse?
  46. curs_hide    DW    1        ; non zero if text cursor should be hidden
  47.  
  48. CODESEG
  49. ;************************************************************************
  50. ;*                      Generate a Bell Character                       *
  51. ;*                                                                      *
  52. ;* Purpose:  To generate a "bell character" (i.e., make a noise) to     *
  53. ;*              simulate the effect of outputting a bell character      *
  54. ;*              (control-G) in the output stream.                       *
  55. ;*                                                                      *
  56. ;* Calling Sequence:  zbell();                                          *
  57. ;*                                                                      *
  58. ;************************************************************************
  59. ;* By convention, low-level user-interface I/O routines (often used from*
  60. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  61. ;************************************************************************
  62. PROC C    zbell USES es
  63.     mov    ax, 1760        ; sound a A6
  64.     call    sound C, ax
  65.     xor    ax, ax            ; point to bios data segment
  66.     mov    es, ax
  67.     mov    cl, [BYTE es:046ch]    ; timer tick counter (DWORD)
  68.     inc    cl
  69.     inc    cl
  70. @@loop:
  71.     cmp    [BYTE es:046ch], cl    ; already 2 ticks away ?
  72.     jnz    @@loop
  73.     call    nosound C
  74.     ret
  75. ENDP    zbell
  76.  
  77. ;************************************************************************
  78. ;*                              Open a File                             *
  79. ;*                                                                      *
  80. ;* Calling sequence:  stat = zopen(handle, pathname, access_code, length)*
  81. ;*                      where:  int *handle - location to store handle  *
  82. ;*                                              returned by open request*
  83. ;*                              char *pathname - zero terminated string *
  84. ;*                                              containing the file's   *
  85. ;*                                              pathname                *
  86. ;*                              int access_code - 0=read, 1=write,      *
  87. ;*                                              2=read and write        *
  88. ;*                              int stat - the completion code          *
  89. ;*                                              0=no errors             *
  90. ;*                                              2=file not found        *
  91. ;*                                              4=too many open files   *
  92. ;*                                              5=access denied         *
  93. ;*                                              12=invalid access       *
  94. ;************************************************************************
  95. PROC C    zopen USES si di, @@handle, @@pathname, @@mode, @@lengthptr
  96.     mov    ah, 03dh
  97.     mov    al, [BYTE @@mode]     ; load access code
  98.     mov    dx, [@@pathname]    ; load pointer to pathname
  99.     int    MSDOS
  100.     jc    @@return
  101.     mov    bx, [@@handle]
  102.     mov    [bx], ax         ; Store returned handle value
  103.  
  104.     push    ax
  105.     mov    bx, ax             ; set bx to file handle
  106.     xor    cx, cx
  107.     xor    dx, dx
  108.     mov    ax, 4202h         ; position file pointer at eof
  109.     int    MSDOS
  110.     mov    bx, [@@lengthptr]
  111.     mov    [WORD HIGH DWORD bx], dx; write DoubleWord length
  112.     mov    [WORD LOW DWORD bx], ax
  113.  
  114.     pop    bx
  115.     xor    cx, cx
  116.     xor    dx, dx
  117.     mov    ax, 4200h         ; reset file pointer to beg of file
  118.     int    MSDOS
  119.     xor    ax, ax             ; set return code for normal return
  120. @@return:
  121.     ret                ; return
  122. ENDP    zopen
  123.  
  124. ;************************************************************************
  125. ;*                           Create a File                              *
  126. ;*                                                                      *
  127. ;* Calling sequence:  stat = zcreate(handle, pathname)                  *
  128. ;*                      where:  int *handle - location to store handle  *
  129. ;*                                              returned by open request*
  130. ;*                              char *pathname - zero terminated string *
  131. ;*                                              containing the file's   *
  132. ;*                                              pathname                *
  133. ;*                              int stat - the completion code          *
  134. ;*                                              0=no errors             *
  135. ;*                                              3=path not found        *
  136. ;*                                              4=too many open files   *
  137. ;*                                              5=access denied         *
  138. ;************************************************************************
  139. PROC C    zcreate USES si di, @@handle, @@pathname
  140.     mov    ah, 03ch
  141.     mov    dx, [@@pathname]    ; load pointer to pathname
  142.     mov    cx, 020h         ; create with "archive" attribute
  143.     int    MSDOS
  144.     jc    @@return
  145.     mov    bx, [@@handle]
  146.     mov    [bx], ax         ; Store returned handle value
  147.     xor    ax, ax
  148. @@return:
  149.     ret
  150. ENDP    zcreate
  151.  
  152. ;************************************************************************
  153. ;*                           Close a File                               *
  154. ;*                                                                      *
  155. ;* Calling sequence:  stat = zclose(handle)                             *
  156. ;*                      where:  int handle - handle returned by open    *
  157. ;*                                           request                    *
  158. ;*                              int stat - the completion code          *
  159. ;*                                              0=no errors             *
  160. ;*                                              6=invalid handle        *
  161. ;************************************************************************
  162. PROC C    zclose USES si di, @@handle
  163.     mov    ah, 03eh
  164.     mov    bx, [@@handle]
  165.     int    MSDOS             ; issue close request
  166.     jc    @@return
  167.     xor    ax, ax             ; set return code for normal return
  168. @@return:
  169.     ret
  170. ENDP    zclose
  171.  
  172. ;************************************************************************
  173. ;*                           Read From a File                           *
  174. ;*                                                                      *
  175. ;* Calling sequence:  stat = zread(handle, buffer, length)              *
  176. ;*                      where:  int handle - handle returned by open    *
  177. ;*                                           request                    *
  178. ;*                              char *buffer - address of character     *
  179. ;*                                              buffer into which data  *
  180. ;*                                              is to be read           *
  181. ;*                              int *length - on input, the maximum     *
  182. ;*                                              number of characters    *
  183. ;*                                              which the buffer will   *
  184. ;*                                              hold.  On output, the   *
  185. ;*                                              number of characters    *
  186. ;*                                              actually read.  Note:   *
  187. ;*                                              a return value of zero  *
  188. ;*                                              characters read         *
  189. ;*                                              indicates end of file.  *
  190. ;*                              int stat - the completion code          *
  191. ;*                                              0=no errors             *
  192. ;*                                              5=access denied         *
  193. ;*                                              6=invalid handle        *
  194. ;************************************************************************
  195. PROC C    zread USES si di, @@handle, @@buffer, @@lengthptr
  196.     mov    ah, 03fh
  197.     mov    dx, [@@buffer]
  198.     mov    bx, [@@lengthptr]
  199.     mov    cx, [bx]         ; load length for read
  200.     mov    bx, [@@handle]
  201.     int    MSDOS
  202.     jc    @@return
  203.     mov    bx, [@@lengthptr]
  204.     mov    [bx], ax         ; Store number of characters read
  205.     xor    ax, ax             ; set return code for normal return
  206. @@return:
  207.     ret
  208. ENDP    zread
  209.  
  210. ;************************************************************************
  211. ;*                           Write to a File                            *
  212. ;*                                                                      *
  213. ;* Calling sequence:  stat = zwrite(handle, buffer, length)             *
  214. ;*                      where:  int handle - handle returned by open    *
  215. ;*                              char *buffer - address of character     *
  216. ;*                                              buffer from which data  *
  217. ;*                                              is to be written        *
  218. ;*                              int *length - on input, the number of   *
  219. ;*                                              characters to write.    *
  220. ;*                                              The actual number of    *
  221. ;*                                              characters which were   *
  222. ;*                                              written is returned in  *
  223. ;*                                              "length"                *
  224. ;*                              int stat - the completion code          *
  225. ;*                                              0=no errors             *
  226. ;*                                              5=access denied         *
  227. ;*                                              6=invalid handle        *
  228. ;************************************************************************
  229. PROC C    zwrite    USES si di, @@handle, @@buffer, @@lengthptr
  230.     mov    ah, 040h
  231.     mov    dx, [@@buffer]
  232.     mov    bx, [@@lengthptr]
  233.     mov    cx, [bx]
  234.     mov    bx, [@@handle]
  235.     int    MSDOS             ; issue write request
  236.     jc    @@return
  237.     mov    bx, [@@lengthptr]
  238.     mov    [bx], ax         ; Store number of characters written
  239.     xor    ax, ax             ; set return code for normal return
  240. @@return:
  241.     ret
  242. ENDP    zwrite
  243.  
  244. ;************************************************************************
  245. ;* Move the file pointer right before EOF character and overwrite it    *
  246. ;* to fix the bug in open-extend-file                                   *
  247. ;************************************************************************
  248. PROC C    mov_fptr USES si di, @@handle:WORD
  249.     LOCAL    @@buffer:WORD
  250.  
  251.     mov    al, 2            ; move the pointer to end of file
  252.     mov    dx, -128           ;  and with offset (one record size)
  253.     mov    cx, -1
  254.     mov    ah, MOVPTR
  255.     mov    bx, [@@handle]
  256.     int    MSDOS
  257.     jc    @@return
  258.     or    dx, dx            ; small file?
  259.     jge    @@bigfile
  260.     xor    ax, ax
  261.     xor    cx, cx
  262.     xor    dx, dx
  263.     mov    ah, MOVPTR
  264.     int    MSDOS
  265.     jc    @@return
  266. @@bigfile:
  267.     lea    dx, [@@buffer]
  268. @@loop:
  269.     mov    cx, 1            ; read one character at a time
  270.     mov    ah, RFILE        ; read it
  271.     int    MSDOS
  272.     jc    @@return
  273.     mov    CL, [BYTE @@buffer]
  274.     cmp    CL, CTRL_Z        ; reach eof character?
  275.     je    @@afterEOF
  276.     or    ax, ax            ; at eof, but no eof char?
  277.     je    @@return
  278.     jmp     @@loop
  279.  
  280. @@afterEOF:
  281.     mov    al, 1            ; move the pointer to the current
  282.     mov    dx, -1             ;  location plus offset
  283.     mov    cx, -1
  284.     mov    ah, MOVPTR
  285.     int    MSDOS
  286.     jc    @@return
  287.     mov    cx, 1            ; file pointer points to EOF character
  288.     mov    bx, [@@handle]
  289.     mov    [@@buffer], 0
  290.     lea    dx, [@@buffer]
  291.     mov    ah, WFILE        ; write one byte
  292.     int    MSDOS
  293.     jc    @@return
  294.     mov    al, 1            ; move the pointer to the current
  295.     mov    dx, -1             ;  location plus offset
  296.     mov    cx, dx
  297.     mov    ah, MOVPTR
  298.     mov    bx, [@@handle]        ; file handle
  299.     int    MSDOS
  300.     jc    @@return
  301.     xor    ax, ax
  302. @@return:
  303.     ret
  304. ENDP    mov_fptr
  305.  
  306. ;************************************************************************
  307. ;* Read characters from a string                                        *
  308. ;*                                                                      *
  309. ;* Calling Sequence:  stringrd(page, disp, buffer, &length)             *
  310. ;*   where page,disp:  location of string-fed port                      *
  311. ;*         buffer and length  are as in ZREAD (see above)               *
  312. ;*                                                                      *
  313. ;************************************************************************
  314. ;* By convention, low-level user-interface I/O routines (often used from*
  315. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  316. ;************************************************************************
  317. PROC C    stringrd USES si di ds es, @@page, @@disp, @@buffer, @@lengthptr
  318.     mov    bx, [@@lengthptr]    ;cx=number of chars to transfer
  319.     mov    cx, [bx]
  320.     mov    di, [@@page]         ;Get port page
  321.     mov    dx, di
  322.     push    ds
  323.     ldpage    ds, di
  324.     mov    di, [@@disp]         ;ds:di point to port
  325.     mov    si, [(PORTDEF di).ptr.disp]
  326.     mov    bl, [(PORTDEF di).ptr.page]
  327.     xor    bh, bh
  328.     ldpage    ds, bx
  329.     cmp    [(ANYDEF si).tag], STRTYPE
  330.     jne    @@notstring
  331.     sstrlen    bx, si, OVERHEAD
  332.     ldpage    es, dx         ;Restore ptr to port
  333.     mov    dx, [(PORTDEF es:di).chunk]
  334.     sub    bx, dx             ;Set bx to # of chars left
  335.     jns    @@notpast
  336.     xor    bx, bx             ;Set # of chars left to 0
  337. @@notpast:
  338.     cmp    bx, cx             ;cx = min( # of chars left, maximum)
  339.     jae    @@maximum
  340.     mov    cx, bx
  341. @@maximum:
  342.     add    si, dx             ;Adjust si into string
  343.     add    dx, cx
  344.     mov    [(PORTDEF es:di).chunk], dx
  345.     mov    di, [@@buffer]
  346.     xor    ax, ax
  347.     mov    dx, cx            ;Remember string length
  348.     pop    es            ;Uses C data segment
  349.     cld
  350.     rep    movsb
  351.     jmp     @@storelen
  352.  
  353. @@notstring:
  354.     mov    ax, -1            ;Ax nonzero signals error
  355.     xor    dx, dx
  356.     pop    es            ;Uses C data segment
  357. @@storelen:
  358.     mov    bx, [@@lengthptr]    ;Set LENGTH to # of chars read
  359.     mov    [WORD es:bx], dx
  360.     ret
  361. ENDP    stringrd
  362.  
  363. ;************************************************************************
  364. ;*                           Clear a Window                             *
  365. ;************************************************************************
  366. ;* By convention, low-level user-interface I/O routines (often used from*
  367. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  368. ;************************************************************************
  369. PROC C    zclear    USES si, @@row:word, @@col:word, @@nrows:word, @@ncols:word, @@attrib:word
  370.     LOCAL    @@vidmode
  371.     lea    si, [@@vidmode]
  372.     mov    [WORD si], -1
  373.     mov    ah, [BYTE LOW @@attrib]
  374.     mov    al, SPACE
  375.     mov    [@@attrib], ax
  376. @@loop:
  377.     call    zputc C, [@@row], [@@col], [@@attrib], [@@ncols], si
  378.     inc    [@@row]
  379.     dec    [@@nrows]         ; decrement row count
  380.     jnz    @@loop
  381.     ret
  382. ENDP    zclear
  383.  
  384. ;************************************************************************
  385. ;*        Automatic Cursor Off/On                    *
  386. ;************************************************************************
  387. ;* By convention, low-level user-interface I/O routines (often used from*
  388. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  389. ;************************************************************************
  390. PROC C    zautohiding, @@newvalue:word
  391.     mov    ax, [@@newvalue]
  392.     mov    [curs_hide], ax
  393.     ret
  394. ENDP    zautohiding
  395.  
  396. ;************************************************************************
  397. ;*          Cursor Off/On internal signal for automatic hiding        *
  398. ;*    This feature can be enabled with the function zautohiding        *
  399. ;************************************************************************
  400. ;* By convention, low-level user-interface I/O routines (often used from*
  401. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  402. ;************************************************************************
  403. PROC C    zcuroff    USES si di    ; !!! SAME AS NEXT PROCEDURE !!!
  404.     cmp    [mouse_use], 0
  405.     je    @@nomouse
  406.     mov    ax, 2            ; hide mouse
  407.     int    33h
  408. @@nomouse:
  409.     mov    ah, 03          ; get the cursor position & mode
  410.     xor    bh, bh
  411.     int    IBM_CRT
  412.     mov    ah, ch
  413.     and    ah, CURSMASK        ; cursor already cleared ?
  414.     cmp    ah, NOCURSOR
  415.     je    @@return
  416.     or    cx, cx            ; this occur after CGA graph init...
  417.     jz    @@return
  418.     mov    [curs_sav], cx         ; save it for restoration
  419.     mov    ch, NOCURSOR
  420. set_cursor:
  421.     cmp    [curs_hide], 0        ; when no hiding, skip BIOS call
  422.     jz    @@skip
  423.     mov    ah, 01h
  424.     int    IBM_CRT         ; turn the cursor off
  425. @@skip:
  426.     push    es
  427.     call    is_graph_mode C        ; need to plot off a cursor ?
  428.     pop    es
  429.     or    ax, ax
  430.     jz    @@return
  431.     mov    ax, 09dbh         ; write a solid block
  432.     mov    cx, 1
  433.     mov    bx, 0ffh        ; xor to current char
  434.     int    IBM_CRT
  435. cursor_ret:
  436. @@return:
  437.     ret
  438. ENDP    zcuroff
  439.  
  440. PROC C    zcuron    USES si di     ; !!! SAME AS PREVIOUS PROCEDURE !!!
  441.     cmp    [mouse_use], 0        ; is it off, or first use?
  442.     je    @@nomouse
  443.     test    [mouse_use], 2        ; disable first MouseOn()
  444.     jnz    @@regular
  445.     or    [mouse_use], 2        ; set regular flag
  446.     jmp    @@nomouse
  447. @@regular:
  448.     mov    ax, 1            ; show mouse
  449.     int    33h
  450. @@nomouse:
  451.     mov    ah, 03          ; get the cursor position & mode
  452.     xor    bh, bh
  453.     int    IBM_CRT
  454.     or    cx, cx            ; this occur after CGA graph init...
  455.     jz    @@restore
  456.     mov    ah, ch
  457.     and    ah, CURSMASK        ; cursor already on ?
  458.     cmp    ah, NOCURSOR
  459.     jne    cursor_ret
  460. @@restore:
  461.     mov    cx, [curs_sav]
  462.     jmp    set_cursor        ; branch to similar code
  463. ENDP    zcuron
  464.  
  465. ;************************************************************************
  466. ;*                           Put Cursor                                 *
  467. ;************************************************************************
  468. ;* By convention, low-level user-interface I/O routines (often used from*
  469. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  470. ;************************************************************************
  471. PROC C    zputcur    USES si di es, @@row:word, @@col:word
  472.     mov    dh, [BYTE @@row]
  473.     mov    dl, [BYTE @@col]
  474.     xor    bh, bh             ; Page number
  475.     mov    ah, 02h         ; load "put cursor" code
  476.     int    IBM_CRT
  477.     ret
  478. ENDP    zputcur
  479.  
  480. ;************************************************************************
  481. ;*                   Scroll Window Up one line                *
  482. ;************************************************************************
  483. ;* By convention, low-level user-interface I/O routines (often used from*
  484. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  485. ;************************************************************************
  486. PROC C    zscroll    USES si, @@line, @@col, @@nline, @@ncols, @@attr
  487.     LOCAL    @@vidmode
  488.     mov    dh, [BYTE @@nline]
  489.     dec    dh             ; if just one line, blank it only !
  490.     jz    @@blank
  491.     mov    dl, [BYTE @@ncols]
  492.     dec    dl
  493.     mov    ch, [BYTE @@line]
  494.     mov    cl, [BYTE @@col]
  495.     mov    ax, 0601h         ; scroll window down one line
  496.     xor    bh, bh
  497.     add    dx, cx             ; dx=Lower right corner
  498.     push    di
  499.     int    IBM_CRT
  500.     pop    di
  501. @@blank:
  502.     lea    si, [@@vidmode]
  503.     mov    [WORD si], -1
  504.         mov     bl, SPACE
  505.         mov     bh, [BYTE @@attr]
  506.     mov    cx, [WORD @@line]
  507.     add    cl, [BYTE @@nline]
  508.     dec    cl
  509.     call    zputc C, cx, [@@col], bx, [@@ncols], si
  510.     jmp    @@return
  511. @@return:
  512.     ret
  513. ENDP    zscroll
  514.  
  515. ;************************************************************************
  516. ;*                   Scroll Window Down one line                        *
  517. ;************************************************************************
  518. ;* By convention, low-level user-interface I/O routines (often used from*
  519. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  520. ;************************************************************************
  521. PROC C    zscroll_d USES si, @@line, @@col, @@nline, @@ncols, @@attr
  522.     LOCAL    @@vidmode
  523.     mov    dh, [BYTE @@nline]
  524.     dec    dh             ; if just one line, blank it only !
  525.     jz    @@blank
  526.     mov    dl, [BYTE @@ncols]
  527.     dec    dl
  528.     mov    ch, [BYTE @@line]
  529.     mov    cl, [BYTE @@col]
  530.     mov    ax, 0701h         ; scroll window down one line
  531.     xor    bh, bh
  532.     add    dx, cx             ; dx=Lower right corner
  533.     push    di
  534.     int    IBM_CRT
  535.     pop    di
  536. @@blank:
  537.     lea    si, [@@vidmode]
  538.     mov    [WORD si], -1
  539.         mov     bl, SPACE
  540.         mov     bh, [BYTE @@attr]
  541.     call    zputc C, [@@line], [@@col], bx, [@@ncols], si
  542.     jmp    @@return
  543. @@return:
  544.     ret
  545. ENDP    zscroll_d
  546.  
  547. ;************************************************************************
  548. ;*            Graphic/Text mode detection            *
  549. ;*                                    *
  550. ;*    Returns    0 if display is currently in text mode            *
  551. ;*        1 if display is currently in graphic mode        *
  552. ;************************************************************************
  553. ;* By convention, low-level user-interface I/O routines (often used from*
  554. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  555. ;************************************************************************
  556. PROC C    is_graph_mode USES es si di
  557.     mov    ax, 4dd4h        ; detect HP 95 LX (with buggy bios)
  558.     int    15h
  559.     mov    cx, bx
  560.     mov    ah, 0fh
  561.     int    10h            ; as a first shot, see what the BIOS thinks
  562.     cmp    al, 3
  563.     jbe    @@text
  564.     cmp    al, 7            ; these ones are for sure
  565.     je    @@text
  566.     cmp    cx, 'HP'        ; on the '95, 
  567.     je    @@graph            ; if it ain't MONO, it's graphics
  568.  
  569.     call    get_max_cols C        ; calculate buffer size if each
  570.     mov    si, ax            ; char would take 35 bits
  571.     call    get_max_rows C        ; (= minimum graph 5 x 7 chars)
  572.     inc    ax
  573.     mov    dl, 5*7
  574.     mul    dl
  575.     mul    si            ; dx:ax is number of bits used
  576.     mov    si, 8            ; convert to bytes
  577.     div    si
  578.     mov    dx, 40h            ; Bios tables base address
  579.     mov    es, dx
  580.     cmp    [WORD es:4ch], ax    ; compare real size with theoric size
  581.     jb    @@text
  582. @@graph:
  583.     mov    ax, 1
  584.     jmp    @@return
  585. @@text:
  586.     xor    ax, ax
  587. @@return:
  588.     ret
  589. ENDP    is_graph_mode
  590.  
  591. ;************************************************************************
  592. ;*        Output Character & Attribute To Window            *
  593. ;*                                    *
  594. ;* item: low byte contains character                    *
  595. ;*      high byte contains attribute                    *
  596. ;*                                    *
  597. ;* vidmode: Pointer to a free word for storing TEMPORARILY video mode.    *
  598. ;*        This should only be used to avoid testing it more than once *
  599. ;*        during the same operation, but remember that the user is    *
  600. ;*        free to change whenever he wants the video mode and there    *
  601. ;*        should NOT be any global variable remembering video mode.    *
  602. ;*    This variable should contains -1 on first call            *
  603. ;************************************************************************
  604. ;* By convention, low-level user-interface I/O routines (often used from*
  605. ;* assembly language) should preserve the Extra-Segment register (ES).    *
  606. ;************************************************************************
  607. PROC C    zputc    USES ax bx cx dx si di, @@line, @@col, @@item, @@replicate, @@vidmode
  608.     mov    dh, [BYTE @@line]    ; position the cursor
  609.     mov    dl, [BYTE @@col]
  610.     xor    bh, bh             ; page zero
  611.     mov    ah, 02h
  612.     int    IBM_CRT
  613.     mov    bx, [@@vidmode]        ; video mode known ?
  614.     cmp    [WORD bx], 0
  615.     jge    @@proceed
  616.     call    is_graph_mode C        ; else detect it
  617.     mov    bx, [@@vidmode]
  618.     mov    [WORD bx], ax
  619.     or    ax, ax
  620. @@proceed:
  621.     mov    bx, [@@item]         ; load char & attributes
  622.     jz    @@attribok
  623.     push    bx
  624.     mov    bl, bh
  625.     mov    cl, 4            ; use background color
  626.     shr    bl, cl
  627.     push    bx
  628.     mov    cx, [@@replicate]
  629.     xor    bh, bh
  630.     mov    al, 0dbh         ; block character
  631.     mov    ah, 09h
  632.     int    IBM_CRT            ; write the background (using blocks)
  633.     pop    ax
  634.     pop    bx
  635.     cmp    bl, SPACE        ; just blanking ?
  636.     je    @@return
  637.     and    bh, 0fh            ; prepare XOR shape of chars to write
  638.     xor    bh, al
  639.     or    bh, 80h
  640. @@attribok:
  641.     mov    ax, 0900h
  642.     xchg    al, bh            ; page zero
  643.     xchg    al, bl            ; char in al, attribute in bl
  644.     mov    cx, [@@replicate]
  645.     int    IBM_CRT
  646. @@return:
  647.     ret
  648. ENDP    zputc
  649.  
  650.     END
  651.